
#ifndef __ApoQuaternion_H__
#define __ApoQuaternion_H__


namespace Apo {
    class   Quaternion
    {
    public:
        inline Quaternion (
            float fW = 1.0,
            float fX = 0.0, float fY = 0.0, float fZ = 0.0)
		{
			w = fW;
			x = fX;
			y = fY;
			z = fZ;
		}
		/// Construct a quaternion from 4 manual w/x/y/z values
		inline Quaternion(float* valptr)
		{
			memcpy(&w, valptr, sizeof(float)*4);
		}
		/// Array accessor operator
		inline float operator [] ( const size_t i ) const
		{
			assert( i < 4 );
			return *(&w+i);
		}

		/// Array accessor operator
		inline float& operator [] ( const size_t i )
		{
			assert( i < 4 );

			return *(&w+i);
		}
		/// Pointer accessor for direct copying
		inline float* ptr()
		{
			return &w;
		}
		/// Pointer accessor for direct copying
		inline const float* ptr() const
		{
			return &w;
		}
        inline Quaternion& operator= (const Quaternion& rkQ)
		{
			w = rkQ.w;
			x = rkQ.x;
			y = rkQ.y;
			z = rkQ.z;
			return *this;
		}
        Quaternion operator+ (const Quaternion& rkQ) const;
        Quaternion operator- (const Quaternion& rkQ) const;
        Quaternion operator* (const Quaternion& rkQ) const;
        Quaternion operator* (float fScalar) const;
        Quaternion operator- () const;
        inline bool operator== (const Quaternion& rhs) const
		{
			return (rhs.x == x) && (rhs.y == y) &&
				(rhs.z == z) && (rhs.w == w);
		}
        inline bool operator!= (const Quaternion& rhs) const
		{
			return !operator==(rhs);
		}
        // rotation of a vector by a quaternion
        Vector3 operator* (const Vector3& rkVector) const;
        // special values
        static const Quaternion ZERO;
        static const Quaternion IDENTITY;
		float w, x, y, z;
    };
}

#endif 
